/**
 ******************************************************************************
 * @file    bl702_mjpeg.c
 * @version V1.0
 * @date
 * @brief   This file is the standard driver c file
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; COPYRIGHT(c) 2020 Bouffalo Lab</center></h2>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *   3. Neither the name of Bouffalo Lab nor the names of its contributors
 *      may be used to endorse or promote products derived from this software
 *      without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************
 */

#include "bl702_mjpeg.h"
#include "bl702.h"
#include "bl702_glb.h"

/** @addtogroup  BL702_Peripheral_Driver
 *  @{
 */

/** @addtogroup  MJPEG
 *  @{
 */

/** @defgroup  MJPEG_Private_Macros
 *  @{
 */

/*@} end of group MJPEG_Private_Macros */

/** @defgroup  MJPEG_Private_Types
 *  @{
 */

/*@} end of group MJPEG_Private_Types */

/** @defgroup  MJPEG_Private_Variables
 *  @{
 */
static intCallback_Type *mjpegIntCbfArra[MJPEG_INT_ALL] = {NULL};

/*@} end of group MJPEG_Private_Variables */

/** @defgroup  MJPEG_Global_Variables
 *  @{
 */

/*@} end of group MJPEG_Global_Variables */

/** @defgroup  MJPEG_Private_Fun_Declaration
 *  @{
 */

/*@} end of group MJPEG_Private_Fun_Declaration */

/** @defgroup  MJPEG_Private_Functions
 *  @{
 */

/*@} end of group MJPEG_Private_Functions */

/** @defgroup  MJPEG_Public_Functions
 *  @{
 */

/****************************************************************************/ /**
                                                                                * @brief  Mjpeg module init
                                                                                *
                                                                                * @param  cfg: Mjpeg configuration structure pointer
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_Init(MJPEG_CFG_Type *cfg) {
  uint32_t tmpVal;

  /* Disable clock gate */
  GLB_AHB_Slave1_Clock_Gate(DISABLE, BL_AHB_SLAVE1_MJPEG);

  /* disable mjpeg */
  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_1);
  tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_MJPEG_ENABLE);
  BL_WR_REG(MJPEG_BASE, MJPEG_CONTROL_1, tmpVal);

  /* basic stuff */
  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_1);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_YUV_MODE, cfg->yuv);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_Q_MODE, cfg->quality);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_H_BUST, cfg->burst);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_MJPEG_BIT_ORDER, cfg->bitOrderEnable);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_ORDER_U_EVEN, cfg->evenOrderEnable);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_WR_OVER_STOP, cfg->overStopEnable);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_REFLECT_DMY, cfg->reflectDmy);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_LAST_HF_HBLK_DMY, cfg->verticalDmy);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_LAST_HF_WBLK_DMY, cfg->horizationalDmy);
  BL_WR_REG(MJPEG_BASE, MJPEG_CONTROL_1, tmpVal);

  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_2);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_MJPEG_WAIT_CYCLE, cfg->waitCount);
  BL_WR_REG(MJPEG_BASE, MJPEG_CONTROL_2, tmpVal);

  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_FRAME_SIZE);

  switch (cfg->yuv) {
  case MJPEG_YUV422_INTERLEAVE:
  case MJPEG_YUV422_PLANAR:
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_FRAME_WBLK, (cfg->resolutionX + 15) >> 4);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_FRAME_HBLK, (cfg->resolutionY + 7) >> 3);
    break;

  case MJPEG_YUV420:
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_FRAME_WBLK, (cfg->resolutionX + 15) >> 4);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_FRAME_HBLK, (cfg->resolutionY + 15) >> 4);
    break;

  case MJPEG_YUV400:
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_FRAME_WBLK, (cfg->resolutionX + 7) >> 3);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_FRAME_HBLK, (cfg->resolutionY + 7) >> 3);
    break;

  default:
    break;
  }

  BL_WR_REG(MJPEG_BASE, MJPEG_FRAME_SIZE, tmpVal);

  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_SWAP_MODE);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_W_SWAP_MODE, cfg->swapModeEnable);
  BL_WR_REG(MJPEG_BASE, MJPEG_SWAP_MODE, tmpVal);

  /*align buffer to 16 bytes boundary, should be kept the same as CAM module*/
  BL_WR_REG(MJPEG_BASE, MJPEG_YY_FRAME_ADDR, (cfg->bufferCamYY & 0xFFFFFFF0));
  BL_WR_REG(MJPEG_BASE, MJPEG_UV_FRAME_ADDR, (cfg->bufferCamUV & 0xFFFFFFF0));
  BL_WR_REG(MJPEG_BASE, MJPEG_YUV_MEM, (cfg->sizeCamUV << 16) + cfg->sizeCamYY);

  /*align buffer to 16 bytes boundary*/
  BL_WR_REG(MJPEG_BASE, MJPEG_JPEG_FRAME_ADDR, (cfg->bufferMjpeg & 0xFFFFFFF0));
  /*align buffer size in unit of 64 bytes */
  BL_WR_REG(MJPEG_BASE, MJPEG_JPEG_STORE_MEMORY, cfg->sizeMjpeg >> 6);

  /* Clear interrupt */
  BL_WR_REG(MJPEG_BASE, MJPEG_FRAME_FIFO_POP, 0x3F00);

#ifndef BFLB_USE_HAL_DRIVER
  Interrupt_Handler_Register(MJPEG_IRQn, MJPEG_IRQHandler);
#endif
}

/****************************************************************************/ /**
                                                                                * @brief  Mjpeg packet mode configure
                                                                                *
                                                                                * @param  cfg: Packet configuration
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_Packet_Config(MJPEG_Packet_Type *cfg) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_PAKET_CTRL);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_PKET_EN, cfg->packetEnable);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_JEND_TO_PEND, cfg->endToTail);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_PKET_BODY_BYTE, cfg->packetBody);
  BL_WR_REG(MJPEG_BASE, MJPEG_PAKET_CTRL, tmpVal);

  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_HEADER_BYTE);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_HEAD_BYTE, cfg->frameHead);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_TAIL_EXP, cfg->frameTail);
  BL_WR_REG(MJPEG_BASE, MJPEG_HEADER_BYTE, tmpVal);

  BL_WR_REG(MJPEG_BASE, MJPEG_PAKET_HEAD_TAIL, (cfg->packetTail << 16) + cfg->packetHead);
}

/****************************************************************************/ /**
                                                                                * @brief  Mjpeg set YUYV order, only work in interleave mode
                                                                                *
                                                                                * @param  y0: Y0 order
                                                                                * @param  u0: U0 order
                                                                                * @param  y1: Y1 order
                                                                                * @param  v0: V0 order
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_Set_YUYV_Order_Interleave(uint8_t y0, uint8_t u0, uint8_t y1, uint8_t v0) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_1);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_Y0_ORDER, y0);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_U0_ORDER, u0);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_Y1_ORDER, y1);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_V0_ORDER, v0);
  BL_WR_REG(MJPEG_BASE, MJPEG_CONTROL_1, tmpVal);

  MJPEG_Set_YUYV_Order_Planar(0, 1);
}

/****************************************************************************/ /**
                                                                                * @brief  Mjpeg set YY/UV order, only work in planar mode
                                                                                *
                                                                                * @param  yy: YY order
                                                                                * @param  uv: UV order
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_Set_YUYV_Order_Planar(uint8_t yy, uint8_t uv) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_2);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_YY_DVP2AHB_LSEL, yy);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_YY_DVP2AHB_FSEL, yy);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_UV_DVP2AHB_LSEL, uv);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_UV_DVP2AHB_FSEL, uv);
  BL_WR_REG(MJPEG_BASE, MJPEG_CONTROL_2, tmpVal);
}

/****************************************************************************/ /**
                                                                                * @brief  Deinit mjpeg module
                                                                                *
                                                                                * @param  None
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_Deinit(void) {
  // GLB_AHB_Slave2_Reset(BL_AHB_SLAVE2_MJPEG);
}

/****************************************************************************/ /**
                                                                                * @brief  Enable mjpeg module
                                                                                *
                                                                                * @param  None
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_Enable(void) {
  uint32_t tmpVal;

  /* Enable mjpeg module */
  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_1);
  tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_MJPEG_ENABLE);
  BL_WR_REG(MJPEG_BASE, MJPEG_CONTROL_1, tmpVal);
}

/****************************************************************************/ /**
                                                                                * @brief  Disable mjpeg module
                                                                                *
                                                                                * @param  None
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_Disable(void) {
  uint32_t tmpVal;

  /* Disable mjpeg module */
  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_1);
  tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_MJPEG_ENABLE);
  BL_WR_REG(MJPEG_BASE, MJPEG_CONTROL_1, tmpVal);
}

/****************************************************************************/ /**
                                                                                * @brief  Enable&disable mjpeg software mode and set frame count
                                                                                *
                                                                                * @param  count: Frame count
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_SW_Enable(uint8_t count) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_2);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_SW_FRAME, count);
  tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_MJPEG_SW_MODE);
  BL_WR_REG(MJPEG_BASE, MJPEG_CONTROL_2, tmpVal);
  tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_MJPEG_SW_MODE);
  BL_WR_REG(MJPEG_BASE, MJPEG_CONTROL_2, tmpVal);
}

/****************************************************************************/ /**
                                                                                * @brief  MJPEG software mode run, software mode enable first
                                                                                *
                                                                                * @param  None
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_SW_Run(void) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_2);
  tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_MJPEG_SW_RUN);
  BL_WR_REG(MJPEG_BASE, MJPEG_CONTROL_2, tmpVal);
  tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_MJPEG_SW_RUN);
  BL_WR_REG(MJPEG_BASE, MJPEG_CONTROL_2, tmpVal);
}

/****************************************************************************/ /**
                                                                                * @brief  Get one mjpeg frame
                                                                                *
                                                                                * @param  info: Mjpeg frame infomation pointer
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_Get_Frame_Info(MJPEG_Frame_Info *info) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_3);

  info->validFrames   = BL_GET_REG_BITS_VAL(tmpVal, MJPEG_FRAME_VALID_CNT);
  info->curFrameAddr  = BL_RD_REG(MJPEG_BASE, MJPEG_START_ADDR0);
  info->curFrameBytes = (BL_RD_REG(MJPEG_BASE, MJPEG_BIT_CNT0) + 7) >> 3;
  info->curFrameQ     = BL_RD_REG(MJPEG_BASE, MJPEG_Q_MODE0) & 0x3f;
  info->status        = tmpVal;
}

/****************************************************************************/ /**
                                                                                * @brief  Get available count of frames
                                                                                *
                                                                                * @param  None
                                                                                *
                                                                                * @return Frames count
                                                                                *
                                                                                *******************************************************************************/
uint8_t MJPEG_Get_Frame_Count(void) { return BL_GET_REG_BITS_VAL(BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_3), MJPEG_FRAME_VALID_CNT); }

/****************************************************************************/ /**
                                                                                * @brief  Pop one mjpeg frame
                                                                                *
                                                                                * @param  None
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_Pop_Frame(void) { BL_WR_REG(MJPEG_BASE, MJPEG_FRAME_FIFO_POP, 1); }

/****************************************************************************/ /**
                                                                                * @brief  Free current read memory block
                                                                                *
                                                                                * @param  None
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_Current_Block_Clear(void) { BL_WR_REG(MJPEG_BASE, MJPEG_FRAME_FIFO_POP, 0x2); }

/****************************************************************************/ /**
                                                                                * @brief  Current read memory block index
                                                                                *
                                                                                * @param  None
                                                                                *
                                                                                * @return Block number
                                                                                *
                                                                                *******************************************************************************/
MJPEG_Swap_Block_Type MJPEG_Get_Current_Block(void) { return BL_GET_REG_BITS_VAL(BL_RD_REG(MJPEG_BASE, MJPEG_SWAP_MODE), MJPEG_STS_READ_SWAP_IDX); }

/****************************************************************************/ /**
                                                                                * @brief  Get block status, full or not full
                                                                                *
                                                                                * @param  block: Block number
                                                                                *
                                                                                * @return Block status
                                                                                *
                                                                                *******************************************************************************/
BL_Sts_Type MJPEG_Block_Is_Full(MJPEG_Swap_Block_Type block) {
  CHECK_PARAM(IS_MJPEG_SWAP_BLOCK_TYPE(block));

  if (MJPEG_BLOCK_0 == block) {
    return BL_GET_REG_BITS_VAL(BL_RD_REG(MJPEG_BASE, MJPEG_SWAP_MODE), MJPEG_STS_SWAP0_FULL);
  } else {
    return BL_GET_REG_BITS_VAL(BL_RD_REG(MJPEG_BASE, MJPEG_SWAP_MODE), MJPEG_STS_SWAP1_FULL);
  }
}

/****************************************************************************/ /**
                                                                                * @brief  Current read memory block is frame start
                                                                                *
                                                                                * @param  None
                                                                                *
                                                                                * @return Set or reset
                                                                                *
                                                                                *******************************************************************************/
BL_Sts_Type MJPEG_Current_Block_Is_Start(void) { return BL_GET_REG_BITS_VAL(BL_RD_REG(MJPEG_BASE, MJPEG_SWAP_MODE), MJPEG_STS_SWAP_FSTART); }

/****************************************************************************/ /**
                                                                                * @brief  Current read memory block is frame end
                                                                                *
                                                                                * @param  None
                                                                                *
                                                                                * @return Set or reset
                                                                                *
                                                                                *******************************************************************************/
BL_Sts_Type MJPEG_Current_Block_Is_End(void) { return BL_GET_REG_BITS_VAL(BL_RD_REG(MJPEG_BASE, MJPEG_SWAP_MODE), MJPEG_STS_SWAP_FEND); }

/****************************************************************************/ /**
                                                                                * @brief  Get frame remain bit count in last block, only valid when current read memory block is
                                                                                *         frame end
                                                                                *
                                                                                * @param  None
                                                                                *
                                                                                * @return Bit count
                                                                                *
                                                                                *******************************************************************************/
uint32_t MJPEG_Get_Remain_Bit(void) { return BL_RD_REG(MJPEG_BASE, MJPEG_SWAP_BIT_CNT); }

/****************************************************************************/ /**
                                                                                * @brief  Set frame threshold to issue normal interrupt
                                                                                *
                                                                                * @param  count: Frame threshold
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_Set_Frame_Threshold(uint8_t count) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_3);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MJPEG_REG_FRAME_CNT_TRGR_INT, count);
  BL_WR_REG(MJPEG_BASE, MJPEG_CONTROL_3, tmpVal);
}

/****************************************************************************/ /**
                                                                                * @brief  MJPEG Enable Disable Interrupt
                                                                                *
                                                                                * @param  intType: MJPEG Interrupt Type
                                                                                * @param  intMask: Enable or Disable
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_IntMask(MJPEG_INT_Type intType, BL_Mask_Type intMask) {
  uint32_t tmpVal;

  /* Check the parameters */
  CHECK_PARAM(IS_MJPEG_INT_TYPE(intType));
  CHECK_PARAM(IS_BL_MASK_TYPE(intMask));

  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_3);

  switch (intType) {
  case MJPEG_INT_NORMAL:
    if (intMask == UNMASK) {
      /* Enable this interrupt */
      tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_NORMAL_EN);
    } else {
      /* Disable this interrupt */
      tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_INT_NORMAL_EN);
    }

    break;

  case MJPEG_INT_CAM_OVERWRITE:
    if (intMask == UNMASK) {
      /* Enable this interrupt */
      tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_CAM_EN);
    } else {
      /* Disable this interrupt */
      tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_INT_CAM_EN);
    }

    break;

  case MJPEG_INT_MEM_OVERWRITE:
    if (intMask == UNMASK) {
      /* Enable this interrupt */
      tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_MEM_EN);
    } else {
      /* Disable this interrupt */
      tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_INT_MEM_EN);
    }

    break;

  case MJPEG_INT_FRAME_OVERWRITE:
    if (intMask == UNMASK) {
      /* Enable this interrupt */
      tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_FRAME_EN);
    } else {
      /* Disable this interrupt */
      tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_INT_FRAME_EN);
    }

    break;

  case MJPEG_INT_BACK_IDLE:
    if (intMask == UNMASK) {
      /* Enable this interrupt */
      tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_IDLE_EN);
    } else {
      /* Disable this interrupt */
      tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_INT_IDLE_EN);
    }

    break;

  case MJPEG_INT_SWAP:
    if (intMask == UNMASK) {
      /* Enable this interrupt */
      tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_SWAP_EN);
    } else {
      /* Disable this interrupt */
      tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_INT_SWAP_EN);
    }

    break;

  case MJPEG_INT_ALL:
    if (intMask == UNMASK) {
      /* Enable all interrupt */
      tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_NORMAL_EN);
      tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_CAM_EN);
      tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_MEM_EN);
      tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_FRAME_EN);
      tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_IDLE_EN);
      tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_SWAP_EN);
    } else {
      /* Disable all interrupt */
      tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_INT_NORMAL_EN);
      tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_INT_CAM_EN);
      tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_INT_MEM_EN);
      tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_INT_FRAME_EN);
      tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_INT_IDLE_EN);
      tmpVal = BL_CLR_REG_BIT(tmpVal, MJPEG_REG_INT_SWAP_EN);
    }

    break;

  default:
    break;
  }

  BL_WR_REG(MJPEG_BASE, MJPEG_CONTROL_3, tmpVal);
}

/****************************************************************************/ /**
                                                                                * @brief  MJPEG Interrupt Clear
                                                                                *
                                                                                * @param  intType: MJPEG Interrupt Type
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_IntClr(MJPEG_INT_Type intType) {
  uint32_t tmpVal;

  CHECK_PARAM(IS_MJPEG_INT_TYPE(intType));

  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_FRAME_FIFO_POP);

  switch (intType) {
  case MJPEG_INT_NORMAL:
    tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_NORMAL_CLR);
    break;

  case MJPEG_INT_CAM_OVERWRITE:
    tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_CAM_CLR);
    break;

  case MJPEG_INT_MEM_OVERWRITE:
    tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_MEM_CLR);
    break;

  case MJPEG_INT_FRAME_OVERWRITE:
    tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_FRAME_CLR);
    break;

  case MJPEG_INT_BACK_IDLE:
    tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_IDLE_CLR);
    break;

  case MJPEG_INT_SWAP:
    tmpVal = BL_SET_REG_BIT(tmpVal, MJPEG_REG_INT_SWAP_CLR);
    break;

  case MJPEG_INT_ALL:
    tmpVal = 0x3F00;

  default:
    break;
  }

  BL_WR_REG(MJPEG_BASE, MJPEG_FRAME_FIFO_POP, tmpVal);
}

/****************************************************************************/ /**
                                                                                * @brief  Install mjpeg interrupt callback function
                                                                                *
                                                                                * @param  intType: MJPEG interrupt type
                                                                                * @param  cbFun: Pointer to interrupt callback function. The type should be void (*fn)(void)
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
void MJPEG_Int_Callback_Install(MJPEG_INT_Type intType, intCallback_Type *cbFun) {
  /* Check the parameters */
  CHECK_PARAM(IS_MJPEG_INT_TYPE(intType));

  mjpegIntCbfArra[intType] = cbFun;
}

/****************************************************************************/ /**
                                                                                * @brief  Mjpeg interrupt handler
                                                                                *
                                                                                * @param  None
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
#ifndef BFLB_USE_HAL_DRIVER
void MJPEG_IRQHandler(void) {
  uint32_t tmpVal;

  tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_3);

  if (BL_IS_REG_BIT_SET(tmpVal, MJPEG_STS_NORMAL_INT)) {
    BL_WR_REG(MJPEG_BASE, MJPEG_FRAME_FIFO_POP, 0x100);

    if (mjpegIntCbfArra[MJPEG_INT_NORMAL] != NULL) {
      /* call the callback function */
      mjpegIntCbfArra[MJPEG_INT_NORMAL]();
    }
  }

  if (BL_IS_REG_BIT_SET(tmpVal, MJPEG_STS_CAM_INT)) {
    BL_WR_REG(MJPEG_BASE, MJPEG_FRAME_FIFO_POP, 0x200);

    if (mjpegIntCbfArra[MJPEG_INT_CAM_OVERWRITE] != NULL) {
      /* call the callback function */
      mjpegIntCbfArra[MJPEG_INT_CAM_OVERWRITE]();
    }
  }

  if (BL_IS_REG_BIT_SET(tmpVal, MJPEG_STS_MEM_INT)) {
    BL_WR_REG(MJPEG_BASE, MJPEG_FRAME_FIFO_POP, 0x400);

    if (mjpegIntCbfArra[MJPEG_INT_MEM_OVERWRITE] != NULL) {
      /* call the callback function */
      mjpegIntCbfArra[MJPEG_INT_MEM_OVERWRITE]();
    }
  }

  if (BL_IS_REG_BIT_SET(tmpVal, MJPEG_STS_FRAME_INT)) {
    BL_WR_REG(MJPEG_BASE, MJPEG_FRAME_FIFO_POP, 0x800);

    if (mjpegIntCbfArra[MJPEG_INT_FRAME_OVERWRITE] != NULL) {
      /* call the callback function */
      mjpegIntCbfArra[MJPEG_INT_FRAME_OVERWRITE]();
    }
  }

  if (BL_IS_REG_BIT_SET(tmpVal, MJPEG_STS_IDLE_INT)) {
    BL_WR_REG(MJPEG_BASE, MJPEG_FRAME_FIFO_POP, 0x1000);

    if (mjpegIntCbfArra[MJPEG_INT_BACK_IDLE] != NULL) {
      /* call the callback function */
      mjpegIntCbfArra[MJPEG_INT_BACK_IDLE]();
    }
  }

  if (BL_IS_REG_BIT_SET(tmpVal, MJPEG_STS_SWAP_INT)) {
    BL_WR_REG(MJPEG_BASE, MJPEG_FRAME_FIFO_POP, 0x2000);

    if (mjpegIntCbfArra[MJPEG_INT_SWAP] != NULL) {
      /* call the callback function */
      mjpegIntCbfArra[MJPEG_INT_SWAP]();
    }
  }
}
#endif

/*@} end of group MJPEG_Public_Functions */

/*@} end of group MJPEG */

/*@} end of group BL702_Peripheral_Driver */
